home *** CD-ROM | disk | FTP | other *** search
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Forecastfox.
- *
- * The Initial Developer of the Original Code is
- * Jon Stritar <jstritar@MIT.EDU>.
- * Portions created by the Initial Developer are Copyright (C) 2005
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Jon Stritar <jstritar@MIT.EDU>
- * Richard Klein <richwklein@mchsi.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
- const CLASS_ID = Components.ID("{CBD8A32B-0F47-4ac0-947D-D72E7ECB85F3}");
- const CLASS_NAME = "Forecastfox Parser Component";
- const CONTRACT_ID = "@ensolis.com/forecastfox/parser;1";
- const nsIDOMXPathResult = Components.interfaces.nsIDOMXPathResult;
- const ffIError = Components.interfaces.ffIError;
- const ffIDisk = Components.interfaces.ffIDisk;
-
- /******************************************************************************
- * ffParser Component
- ******************************************************************************/
- function ffParser() {};
- ffParser.prototype = {
- _xpath: null,
- _xresolve: null,
- _manager: null,
- _bundle: null,
- _data: null,
- _targets: null,
- _lists: null,
- _masks: null,
-
- start: function()
- {
- var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService);
- this._xpath = Components.classes["@mozilla.org/dom/xpath-evaluator;1"].getService(Components.interfaces.nsIDOMXPathEvaluator);
- this._xresolve = Components.classes["@ensolis.com/forecastfox/resolver;1"].createInstance(Components.interfaces.nsIDOMXPathNSResolver);
- this._manager = Components.classes["@ensolis.com/forecastfox/manager;1"].getService(Components.interfaces.ffIManager);
- this._bundle = sbs.createBundle("chrome://forecastfox/locale/forecastfox.properties");
- this._data = new Object();
- this._loadParser();
- },
-
- stop: function()
- {
- this._xpath = null;
- this._xresolve = null;
- this._manager = null;
- this._bundle = null;
- this._data = null;
- this._targets = null;
- this._lists = null;
- this._masks = null;
- },
-
- open: function(aDoc, aTarget, aNew)
- {
- //return error if parse doc not loaded
- if (!this._targets)
- return this._createError(ffIError.SEVERITY_ERROR, "ff.parser.load", null, null);
-
- //do routine for new document
- if (aNew) {
-
- //return error if aDoc not formed
- if (!this._manager.disk.valid(aDoc))
- return this._createError(ffIError.SEVERITY_ERROR, "ff.parser.formed", null, null);
-
- //check for error messages
- this._build(aDoc, "error");
- var message = this.getValue("error", "message", null);
- if (message != "")
- return this._createError(ffIError.SEVERITY_ERROR, null, message, message);
-
- //check units
- this._build(aDoc, "units");
- if (this.getValue("units", "ut", null) == "")
- return this._createError(ffIError.SEVERITY_ERROR, "ff.parser.units", null, null);
- };
-
- //build target
- this._build(aDoc, aTarget);
-
- //build includes
- var target = this._targets[aTarget];
- var data = new Object();
- for (var j=0; j<target.includes.length; j++) {
- this._build(aDoc, target.includes[j]);
- data = this._merge(data, this._data[target.includes[j]][0]);
- };
-
- //merge includes into each context
- //only merge first context of the include
- for (j=0; j<target.contexts.length; j++)
- this._data[aTarget][j] = this._merge(data, this._data[aTarget][j]);
-
-
- //parser success return informational error
- return this._createError(ffIError.SEVERITY_INFO, null, "", "");
- },
-
- getItems: function(aTarget, aCount)
- {
- var items = new Array();
- for (i in this._data[aTarget][0]) {
- if (!this._data[aTarget][0][i].hidden)
- items.push(i);
- }
-
- aCount.value = items.length;
- return items;
- },
-
- getDescription: function(aTarget, aItem)
- {
- //get the item
- var item = this._getItem(aTarget, aItem, 0);
- if (!item)
- return "";
-
- return item.description;
- },
-
- getValue: function(aTarget, aItem, aIndex)
- {
- //get the item
- var item = this._getItem(aTarget, aItem, aIndex);
- if (!item)
- return "";
-
- //no mask so just return value
- if (item.mask == "" || item.value == "N/A")
- return item.value;
-
- //return mask from converter
- var mask = this._masks[item.mask];
- if (mask) {
- var units = this._manager.branch.getComplexValue("units.current", Components.interfaces.nsIPrefLocalizedString).data;
- var conversion = this._manager.branch.getComplexValue("units." + item.mask + "." + units, Components.interfaces.nsIPrefLocalizedString).data;
- return this.getConverter(item.mask, units, conversion, item.value);
- };
-
- //not a named mask so return updated value
- var val;
- try {
- mask = item.mask;
- mask = mask.replace("$VAL", "'" + String(item.value) + "'");
- val = eval(mask);
- } catch(e) {
- val = item.value;
- };
-
- return val;
- },
-
- getValueRaw: function(aTarget, aItem, aIndex)
- {
- //get the item
- var item = this._getItem(aTarget, aItem, aIndex);
-
- //return the raw value
- if (!item)
- return null;
-
- return item.value;
- },
-
- setLabel: function(aLabel, aTarget, aIndex)
- {
- var label = aLabel;
- var comp = this;
-
- //XXX should come up with better solution than try/catch
- try {
- label = aLabel.replace(/\[[^\[\]]+\]/g,
- function (str) {
- var item = str.substring(1, str.length-1);
- if (comp._getItem(aTarget, item, aIndex))
- return comp.getValue(aTarget, item, aIndex);
- else
- return str;
- }
- )
- } catch (e) {};
- return label;
- },
-
- getConverters: function(aMask, aUnits, aCount)
- {
- var items = new Array();
- var converters = this._masks[aMask][parseInt(aUnits)];
- for (i in converters)
- items.push(i);
-
- aCount.value = items.length;
- return items;
- },
-
- getConverter: function(aMask, aUnits, aConverter, aValue)
- {
- //get the converter for that mask, unit, converter
- var converter = this._masks[aMask][parseInt(aUnits)][aConverter];
-
- //replace value in calc
- var calc;
- if (aValue != null)
- calc = converter["calc"].replace("$VAL", aValue);
- else
- calc = "''";
-
- //replace calc with value
- var val = converter["value"].replace("$CALC", calc);
- return eval(val);
- },
-
- _getItem: function(aTarget, aItem, aIndex)
- {
- var data;
- if (aIndex)
- data = this._data[aTarget][aIndex];
- else
- data = this._data[aTarget][0];
-
- //item not found
- var item = data[aItem];
- if (!item)
- return null;
- else
- return item;
- },
-
- _build: function(aDoc, aTarget)
- {
- var i, j, k, l;
-
- //build all with no document
- if (!aTarget) {
- for (i in this._targets)
- this._build(aDoc, i);
- return;
- };
-
- //get the target we are building
- var target = this._targets[aTarget];
-
- //do list based on context
- this._data[aTarget] = new Array();
- for (k=0; k<target.contexts.length; k++)
- this._data[aTarget].push(this._buildList(aDoc, target.contexts[k], target.list));
- },
-
- _buildList: function(aDoc, aContext, aList)
- {
- var list = this._lists[aList];
- var data = new Object();
- var context = (!aDoc || !aContext) ? null: this._evalPath(aDoc, aContext);
- var i, item;
-
- //loop through items in list
- for(i in list) {
- item = this._buildItem(context, list[i]);
- data[i] = item;
- };
-
- return data;
- },
-
- _buildItem: function(aContext, aItem)
- {
- var item = new Object();
- item.description = aItem.description;
- item.type = aItem.type;
- item.hidden = aItem.hidden;
- item.mask = aItem.mask;
-
- //no context so empty item
- if (!aContext) {
- item.value = this._setValue(null, item.type);
- return item;
- };
-
- //no path
- var node, calc;
- if (aItem.path == "")
- item.value = this._setValue(null, item.type);
- else {
- //see if we have a calc
- if (aItem.calc != "") {
- node = this._evalPath(aContext, aItem.calc);
- if (!node)
- calc = aItem.path.replace("$CALC", "''");
- else
- calc = aItem.path.replace("$CALC", node.textContent);
- } else
- calc = aItem.path.replace("$CALC", "''");
-
- //try to resolve item path
- node = this._evalPath(aContext, calc);
- if (!node)
- item.value = this._setValue(null, item.type);
- else
- item.value = this._setValue(node.textContent, item.type);
- };
-
- return item;
- },
-
- _setValue: function(aValue, aType)
- {
- var val = null;
- switch(aType) {
- case "string":
- defaut:
- val = (!aValue) ? "" : String(aValue);
- break;
- case "number":
- val = (!aValue) ? 0 : Number(aValue);
- if (aValue == "N/A")
- val = "N/A";
- break;
- case "boolean":
- val = (aValue == "true" || aValue == "1") ? true : false;
- break;
- };
-
- return val;
- },
-
- _evalPath: function(aNode, aExpr)
- {
- var result = null;
-
- try {
- var results = this._xpath.evaluate(aExpr, aNode, this._xresolve, nsIDOMXPathResult.ANY_TYPE, null);
- result = results.iterateNext();
- } catch(e) {};
-
- return result;
- },
-
- _createError: function(aSeverity, aName, aDescription, aTooltip)
- {
- var description = (aName) ? this._bundle.GetStringFromName(aName + ".label") : aDescription;
- var tooltip = (aName) ? this._bundle.GetStringFromName(aName + ".tooltip") : aTooltip;
- var error = Components.classes["@ensolis.com/forecastfox/error;1"].createInstance(Components.interfaces.ffIError);
- error.init(aSeverity, "@ensolis.com/forecastfox/parser;1", description, tooltip);
- return error;
- },
-
- _createList: function(aList)
- {
- //make global list a new array
- var name = aList.getAttribute("name");
- this._lists[name] = new Object();
-
- //create each item that goes in list
- for (var i=0; i<aList.childNodes.length; i++) {
- if (aList.childNodes[i].localName != "item")
- continue;
-
- this._createItem(name, aList.childNodes[i]);
- }
- },
-
- _createTarget: function(aTarget)
- {
- //make global task an item
- var name = aTarget.getAttribute("name");
- this._targets[name] = new Object();
-
- //get the list
- this._targets[name].list = aTarget.getAttribute("list");
-
- //get the context
- var contexts = new Array();
- var i;
- for (i=0; i<aTarget.childNodes.length; i++) {
- if (aTarget.childNodes[i].localName != "context")
- continue;
- contexts.push(aTarget.childNodes[i].getAttribute("path"));
- };
-
- //get the includes
- var includes = new Array();
- for (i=0; i<aTarget.childNodes.length; i++) {
- if (aTarget.childNodes[i].localName != "include")
- continue;
- includes.push(aTarget.childNodes[i].getAttribute("target"));
- };
-
- this._targets[name].contexts = contexts;
- this._targets[name].includes = includes;
- },
-
- _createItem: function(aList, aItem)
- {
- //create new item object
- var item = new Object();
- item.name = aItem.getAttribute("name");
- item.type = aItem.getAttribute("type");
- item.hidden = aItem.hasAttribute("hidden");
- item.path = (aItem.hasAttribute("path")) ? aItem.getAttribute("path") : "";
- item.value = this._setValue(null, item.type);
-
- //get description
- try {
- if (aItem.hasAttribute("alias"))
- item.description = this._bundle.GetStringFromName("ff.labels." + aItem.getAttribute("alias"));
- else
- item.description = this._bundle.GetStringFromName("ff.labels." + item.name);
- } catch(e) {
- item.description = item.name;
- }
-
- //get mask
- if (aItem.hasAttribute("mask"))
- item.mask = aItem.getAttribute("mask");
- else
- item.mask = "";
-
- //get calc
- if (aItem.hasAttribute("calc"))
- item.calc = aItem.getAttribute("calc");
- else
- item.calc = "";
-
- this._lists[aList][item.name] = item;
- },
-
- _loadParser: function()
- {
- //read file
- var file = this._manager.disk.get("parser.xml", ffIDisk.TYPE_DEFAULTS);
- if (!file.exists() || !file.isReadable())
- return
- var doc = this._manager.disk.read(file);
-
- //get target and list elements
- var targets = doc.getElementsByTagName("target");
- var lists = doc.getElementsByTagName("list");
- var masks = doc.getElementsByTagName("mask");
-
- var i, j, k;
- if (targets.length == 0 || lists.length == 0 || masks == 0)
- return;
-
- //create our masks
- this._masks = new Object();
- for (i=0; i<masks.length; i++) {
- //create an array for the mask
- var name = masks[i].getAttribute("name");
- this._masks[name] = new Array();
-
- //get the different unit conversions
- var conversions = masks[i].getElementsByTagName("conversion");
- for (j=0; j<conversions.length; j++) {
- var conversion = new Object();
-
- //get the converters for that unit
- var converters = conversions[j].getElementsByTagName("converter");
- for (k=0; k<converters.length; k++) {
- var converter = converters[k].getAttribute("name");
- conversion[converter] = new Object();
- conversion[converter].calc = converters[k].getAttribute("calc");
- conversion[converter].value = converters[k].getAttribute("value");
- };
-
- //add the conversion to the mask array
- this._masks[name].push(conversion);
- };
- };
-
- //create our lists and targets
- this._lists = new Object();
- this._targets = new Object();
-
-
- for (i=0; i<lists.length; i++)
- this._createList(lists[i]);
- for (i=0; i<targets.length; i++)
- this._createTarget(targets[i]);
-
- //do an empty build
- this._build(null, null);
- },
-
- _merge: function(aObject1, aObject2)
- {
- var data = new Object();
-
- for (i in aObject2)
- data[i] = aObject2[i];
-
- for (i in aObject1)
- data[i] = aObject1[i];
-
- return data;
- },
-
- ///////////////////////////
- // nsIClassInfo
- getInterfaces: function(aCount)
- {
- var ifaces = new Array();
- ifaces.push(Components.interfaces.ffIParser);
- ifaces.push(Components.interfaces.nsIClassInfo);
- ifaces.push(Components.interfaces.nsISupports);
- aCount.value = ifaces.length;
- return ifaces;
- },
-
- getHelperForLanguage: function(aLanguage) { return null; },
- get contractID() { return CONTRACT_ID; },
- get classID() { return CLASS_ID; },
- get classDescription() { return CLASS_NAME; },
- get implementationLanguage() { return Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT; },
- get flags() { return Components.interfaces.nsIClassInfo.SINGLETON; },
-
- ///////////////////////////
- // nsISupports
- QueryInterface: function (aIID)
- {
- if (!aIID.equals(Components.interfaces.ffIParser) &&
- !aIID.equals(Components.interfaces.nsIClassInfo) &&
- !aIID.equals(Components.interfaces.nsISupports))
- throw Components.results.NS_ERROR_NO_INTERFACE;
- return this;
- }
- };
-
- /******************************************************************************
- * XPCOM Functions for construction and registration
- ******************************************************************************/
- var gModule = {
- _firstTime: true,
- registerSelf: function(aCompMgr, aFileSpec, aLocation, aType)
- {
- if (this._firstTime) {
- this._firstTime = false;
- throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
- };
- aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
- aCompMgr.registerFactoryLocation(CLASS_ID, CLASS_NAME, CONTRACT_ID, aFileSpec, aLocation, aType);
- },
-
- unregisterSelf: function(aCompMgr, aLocation, aType)
- {
- aCompMgr = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
- aCompMgr.unregisterFactoryLocation(CLASS_ID, aLocation);
- },
-
- getClassObject: function(aCompMgr, aCID, aIID)
- {
- if (!aIID.equals(Components.interfaces.nsIFactory))
- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
-
- if (aCID.equals(CLASS_ID))
- return gFactory;
-
- throw Components.results.NS_ERROR_NO_INTERFACE;
- },
-
- canUnload: function(aCompMgr) { return true; }
- };
-
- var gFactory = {
- createInstance: function (aOuter, aIID)
- {
- if (aOuter != null)
- throw Components.results.NS_ERROR_NO_AGGREGATION;
- return (new ffParser()).QueryInterface(aIID);
- }
- };
-
- function NSGetModule(aCompMgr, aFileSpec) { return gModule; }